package convert

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
)

func ToString(i any) string {
	if i == nil {
		return ""
	}
	switch t := i.(type) {
	case string:
		return t
	case int:
		return strconv.Itoa(t)
	case int64:
		return strconv.FormatInt(t, 10)
	case float64:
		return strconv.FormatFloat(t, 'f', -1, 64)
	case bool:
		return strconv.FormatBool(t)
	case fmt.Stringer:
		return t.String()
	default:
		if b, err := json.Marshal(i); err == nil {
			return string(b)
		}
		return ""
	}
}

func Atoi(s string) int {
	i, _ := strconv.Atoi(s)
	return i
}

func Atof(s string) float64 {
	f, _ := strconv.ParseFloat(s, 64)
	return f
}

func Reverse(s string) string {
	runes := []rune(s)
	for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
		runes[from], runes[to] = runes[to], runes[from]
	}
	return string(runes)
}

func ReverseBytes(b []byte) {
	for from, to := 0, len(b)-1; from < to; from, to = from+1, to-1 {
		b[from], b[to] = b[to], b[from]
	}
}

func Xor(data, key []byte) []byte {
	ret := make([]byte, len(data))
	for i := 0; i < len(data); i++ {
		ret[i] = data[i] ^ key[i%len(key)]
	}
	return ret
}

const (
	kb = 1024
	mb = kb * 1024
	gb = mb * 1024
	tb = gb * 1024
)

func FmtSize(size int) string {
	if size < kb {
		return trim_zero(float64(size)) + "B"
	}
	if size < mb {
		return trim_zero(float64(size)/float64(kb)) + "K"
	}
	if size < gb {
		return trim_zero(float64(size)/float64(mb)) + "M"
	}
	if size < tb {
		return trim_zero(float64(size)/float64(gb)) + "G"
	}
	return trim_zero(float64(size)/float64(tb)) + "T"
}

func trim_zero(f float64) string {
	// return strings.TrimRight(fmt.Sprintf("%.2f", f), ".0")
	s := fmt.Sprintf("%.2f", f)
	ss := strings.Split(s, ".")
	ss[1] = strings.TrimRight(ss[1], "0")
	if len(ss[1]) == 0 {
		return ss[0]
	}
	return strings.Join(ss, ".")
}
